package top.saplf.sileny.ext

import android.support.v4.app.Fragment
import android.support.v7.app.AppCompatActivity
import cn.nekocode.rxlifecycle.compact.RxLifecycleCompact
import io.reactivex.Observable
import io.reactivex.Observer
import io.reactivex.android.MainThreadDisposable
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.schedulers.Schedulers

/**
 * @author saplf
 */

object RxActivityResult {
    fun <T> bind(activityResult: IRxActivityResult<T>): Observable<T>
            = ActivityResultObservable(activityResult)
}

interface IRxActivityResult<out T> {
    fun setActivityResultListener(listener: ActivityResultListener<T>?)
}

interface ActivityResultListener<in T> {
    fun onResult(data: T)
}

private class ActivityResultObservable<T>(
        private val activityResult: IRxActivityResult<T>
) : Observable<T>() {
    override fun subscribeActual(observer: Observer<in T>) {
        val listener = Listener(activityResult, observer)
        observer.onSubscribe(listener)
        activityResult.setActivityResultListener(listener)
    }

    private class Listener<in T>(
            private val activityResult: IRxActivityResult<T>,
            private val observer: Observer<in T>
    ) : MainThreadDisposable(), ActivityResultListener<T> {
        override fun onResult(data: T) {
            observer.onNext(data)
        }

        override fun onDispose() {
            activityResult.setActivityResultListener(null)
        }

    }
}

fun <T> Observable<T>.normalCompose(fragment: Fragment): Observable<T> {
    return this.subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .compose(RxLifecycleCompact.bind(fragment).withObservable())
}

fun <T> Observable<T>.normalCompose(activity: AppCompatActivity): Observable<T> {
    return this.subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .compose(RxLifecycleCompact.bind(activity).withObservable())
}
